package com.fangcang.utils;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.chrono.ChronoLocalDateTime;
import java.time.chrono.Chronology;
import java.time.chrono.HijrahChronology;
import java.time.format.DateTimeFormatter;
import java.time.temporal.IsoFields;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

public class DateUtil {

	public static void main(String[] args) {
		LocalDate today = LocalDate.now();
		// Get the Year, check if it's leap year
		System.out.println("Year " + today.getYear() + " is Leap Year? " + today.isLeapYear());
		// Compare two LocalDate for before and after
		System.out.println("Today is before 01/01/2015? " + today.isBefore(LocalDate.of(2015, 1, 1)));
		// Create LocalDateTime from LocalDate
		System.out.println("Current Time=" + today.atTime(LocalTime.now()));
		// plus and minus operations
		System.out.println("10 days after today will be " + today.plusDays(10));
		System.out.println("3 weeks after today will be " + today.plusWeeks(3));
		System.out.println("20 months after today will be " + today.plusMonths(20));
		System.out.println("10 days before today will be " + today.minusDays(10));
		System.out.println("3 weeks before today will be " + today.minusWeeks(3));
		System.out.println("20 months before today will be " + today.minusMonths(20));
		// Temporal adjusters for adjusting the dates
		System.out.println("First date of this month= " + today.with(TemporalAdjusters.firstDayOfMonth()));
		LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear());
		System.out.println("Last date of this year= " + lastDayOfYear);
		Period period = today.until(lastDayOfYear);
		System.out.println("Period Format= " + period);
		System.out.println("Months remaining in the year= " + period.getMonths());

		testInstant();
		testLocalDateTime();
		testZonedDateTime();
		testDuration();

		testChronology();
		testNewOldDateConversion();
	}

	public static String format(LocalDate date, String pattern) {
		if (pattern == null) {
			return date.format(DateTimeFormatter.ISO_LOCAL_DATE);
		}
		return date.format(DateTimeFormatter.ofPattern(pattern));
	}

	public static long getMinus() {
		Instant instant = Instant.now();
		return instant.toEpochMilli();
	}

	public static void testClock() throws InterruptedException {
		// 时钟提供给我们用于访问某个特定时区的瞬时时间、日期和时间的。
		Clock c1 = Clock.systemUTC(); // 系统默认 UTC时钟（当前瞬时时间 System.currentTimeMillis()）
		System.out.println(c1.millis()); // 每次调用将返回当前瞬时时间（UTC）
		Clock c2 = Clock.systemDefaultZone(); // 系统默认时区时钟（当前瞬时时间）
		Clock c31 = Clock.system(ZoneId.of("Europe/Paris")); // 巴黎时区
		System.out.println(c31.millis()); // 每次调用将返回当前瞬时时间（UTC）
		Clock c32 = Clock.system(ZoneId.of("Asia/Shanghai"));// 上海时区
		System.out.println(c32.millis());// 每次调用将返回当前瞬时时间（UTC）
		Clock c4 = Clock.fixed(Instant.now(), ZoneId.of("Asia/Shanghai"));// 固定上海时区时钟
		System.out.println(c4.millis());

		Thread.sleep(1000);
		System.out.println(c4.millis()); // 不变即时钟时钟在那一个点不动
		Clock c5 = Clock.offset(c1, Duration.ofSeconds(2)); // 相对于系统默认时钟两秒的时钟
		System.out.println(c1.millis());
		System.out.println(c5.millis());
	}

	public static void testInstant() {

		// 瞬时时间相当于以前的 System.currentTimeMillis()
		Instant instant1 = Instant.now();
		System.out.println(instant1.getEpochSecond());// 精确到秒得到相对于 1970-01-01 00:00:00

		System.out.println(instant1.toEpochMilli()); // 精确到毫秒
		Clock clock1 = Clock.systemUTC(); // 获取系统 UTC默认时钟
		Instant instant2 = Instant.now(clock1);// 得到时钟的瞬时时间
		System.out.println(instant2.toEpochMilli());

		Clock clock2 = Clock.fixed(instant1, ZoneId.systemDefault()); // 固定瞬时时间时钟
		Instant instant3 = Instant.now(clock2);// 得到时钟的瞬时时间
		System.out.println(instant3.toEpochMilli());// equals instant1
	}

	public static void testLocalDateTime() {
		// 使用默认时区时钟瞬时时间创建 Clock.systemDefaultZone() -->即相对于 ZoneId.systemDefault()

		LocalDateTime now = LocalDateTime.now();
		System.out.println(now);

		// 自定义时区
		LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Europe/Paris"));

		System.out.println(now2);// 会以相应的时区显示日期
		// 自定义时钟
		Clock clock = Clock.system(ZoneId.of("Asia/Dhaka"));
		LocalDateTime now3 = LocalDateTime.now(clock);

		System.out.println(now3);// 会以相应的时区显示日期
		// 不需要写什么相对时间如 java.util.Date年是相对于 1900月是从 0开始
		// 2013-12-31 23:59
		LocalDateTime d1 = LocalDateTime.of(2013, 12, 31, 23, 59);

		// 年月日时分秒纳秒
		LocalDateTime d2 = LocalDateTime.of(2013, 12, 31, 23, 59, 59, 11);

		// 使用瞬时时间 +时区
		Instant instant = Instant.now();
		LocalDateTime d3 = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
		System.out.println(d3);

		// 解析 String--->LocalDateTime
		LocalDateTime d4 = LocalDateTime.parse("2013-12-31T23:59");
		System.out.println(d4);
		LocalDateTime d5 = LocalDateTime.parse("2013-12-31T23:59:59.999");// 999 毫秒等价于

		System.out.println(d5);
		// 使用 DateTimeFormatter API解析和格式化

		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
		LocalDateTime d6 = LocalDateTime.parse("2013/12/31 23:59:59", formatter);
		System.out.println(formatter.format(d6));
		// 时间获取
		System.out.println(d6.getYear());
		System.out.println(d6.getMonth());
		System.out.println(d6.getDayOfYear());
		System.out.println(d6.getDayOfMonth());
		System.out.println(d6.getDayOfWeek());
		System.out.println(d6.getHour());
		System.out.println(d6.getMinute());
		System.out.println(d6.getSecond());
		System.out.println(d6.getNano());
		// 时间增减
		LocalDateTime d7 = d6.minusDays(1);
		LocalDateTime d8 = d7.plus(1, IsoFields.QUARTER_YEARS);
		// LocalDate即年月日无时分秒
		// LocalTime即时分秒无年月日

		// API和 LocalDateTime类似就不演示了
	}

	public static void testZonedDateTime() {
		// 即带有时区的 date-time存储纳秒、时区和时差（避免与本地 date-time歧义）。
		// API和 LocalDateTime类似，只是多了时差(如 2013-12-20T10:35:711+08:00[Asia/Shanghai])

		ZonedDateTime now = ZonedDateTime.now();
		System.out.println(now);
		ZonedDateTime now2 = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
		System.out.println(now2);

	}

	public static void testDuration() {

		// 表示两个瞬时时间的时间段
		Duration d1 = Duration.between(Instant.ofEpochMilli(System.currentTimeMillis() - 12323123), Instant.now());
		// 得到相应的时差
		System.out.println(d1.toDays());
		System.out.println(d1.toHours());
		System.out.println(d1.toMinutes());

		System.out.println(d1.toMillis());
		System.out.println(d1.toNanos());
		// 1天时差类似的还有如 ofHours()
		Duration d2 = Duration.ofDays(1);
		System.out.println(d2.toDays());
	}

	public static void testChronology() {
		// 提供对 java.util.Calendar的替换，提供对年历系统的支持

		Chronology c = HijrahChronology.INSTANCE;
		ChronoLocalDateTime d = c.localDateTime(LocalDateTime.now());
		System.out.println(d);
	}

	/**
	 * 新旧日期转换
	 */
	public static void testNewOldDateConversion() {
		Instant instant = new Date().toInstant();
		Date date = Date.from(instant);
		System.out.println(instant);
		System.out.println(date);

	}
}
